package android.hermes;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.*;
import java.util.ArrayList;
import java.util.Random;
import android.app.Activity;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;


/**
 *  
 * @author Erik, Tobias & Joakim.
 *
 */

//@SuppressWarnings("unused")
public class Hermes extends Activity implements OnClickListener {
	
	public static final int TXT = 1;
	public static final int IP = 2;
	public static final int MP3 = 3;
	
	//instance varibles
	WifiManager wifi = null;
	Button sendButton, listenButton;
	EditText txtBox;
	TextView inbox;
	AdHocWifiManager adhocWifi;
	InetAddress myIP, otherIP;

    /* (non-Javadoc)
     * @see android.app.Activity#onCreate(android.os.Bundle)
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        adhocWifi = new AdHocWifiManager();

        //the send botton
        sendButton = (Button) findViewById(R.id.sendButton);
        sendButton.setOnClickListener(this);
        //the textbox where you write the textmessage
        txtBox = (EditText) findViewById(R.id.txtBox);
        inbox = (TextView) findViewById(R.id.inbox);
        
        //disable wifi
        wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        wifi.setWifiEnabled(false);
        
        //create dir and move bin
        createDirs();
        moveFiles();
        
        randomizeAndSetMyIP();
        
        //Sätt igång nätverket
        adhocWifi.enableWifi(myIP);
        
        //Starta lyssnarservicen här va?
        //quickRegistering();
        
        startService(new Intent(this, ListenForFriends.class));
        /*try {
			Class cls = Class.forName("ListenForFriends");
			startService(new Intent(this, cls));
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
        
        
        //Försöka ansluta, borde returnera ett resultat så man kan köra
        adhocWifi.connect();
        
        //Eller om det finns nåt i Java som kan kolla...
        
        //if(ansluten) pingLocals(); annars pingar vi med knappen...
        announcePresence();
        
        //
        
    }
    

	/* (non-Javadoc)
     * @see android.view.View.OnClickListener#onClick(android.view.View)
     */
    public void onClick(View v) {
    	
    	announcePresence();
           
    }

	/**
	 * (non-Javadoc)
	 * @see android.os.Handler#handleMessage(android.os.Message)
	 * 
	 */
	private Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			if(msg.what == TXT) {
				String x = (String) msg.obj;
				inbox.setText(inbox.getText() + x);
			
				popMsg(x);
			}
			else if(msg.what == IP) {
				otherIP = (InetAddress) msg.obj;
				popMsg("Got new friend! IP = " + otherIP.toString() + "\n My IP is = " + myIP.toString());
			}
		}
	};

    private void randomizeAndSetMyIP() {
		
    	Random r = new Random();
    	r.setSeed(System.currentTimeMillis());
    	int addr = r.nextInt(253) + 1;
    	try {
			myIP = InetAddress.getByName("192.168.42." + addr);
		} catch (UnknownHostException e) {}
    	
	}
	/**
	 * 
	 */
	private void send(){
    	try {
    		    		
    		InetAddress destIP = InetAddress.getByName("255.255.255.0");
    		//popMsg("Sent to: " + destIP.toString());
			Socket sendSocket = new Socket(otherIP, 6546);
			
			DataOutputStream utdata = new DataOutputStream(sendSocket.getOutputStream());
			
			utdata.writeBytes(txtBox.getText() +" - From: " + myIP.toString() +"\n");
			sendSocket.close();
			
		} catch (Exception e) {
			//error handling
			Hermes.this.popMsg(e.getMessage());
		} 
    	
    }

    /**
     * creates and starts a thread that handles the socketlistener
     */
    private void setupSocketListener(){
    	Thread t = new Thread (new Runnable(){
    		public void run(){
    			while(true){
    			Socket connectionSocket;
    			BufferedReader indata;
    
	    			try {
    					ServerSocket welcomeSocket = new ServerSocket(6546);
						String tempS;				
						connectionSocket = welcomeSocket.accept();
						indata = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
							
						Message msg = new Message();
						tempS = indata.readLine();
						msg.what = TXT;
						msg.obj = tempS;
						
						handler.sendMessage(msg);
						connectionSocket.close();
						welcomeSocket.close();
						
					} catch (IOException e) {
						//error handling
						Hermes.this.popMsg("fel vid lyssning");
					}
    			}
    		}
    	});
    	t.start();

    }
    /**
     * @param message
     * Displays a simple toast 
     */
    public void popMsg(String message) {
    	Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
	}
    


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    /**
     * Create the necessary directories
     */
    private void createDirs() {
    	File dir = new File("/data/data/android.hermes/");
    	if (dir.exists() == false) {
    			Hermes.this.popMsg("Application data-dir does not exist!");
    	}
    	else {
	    	dir = new File("/data/data/android.hermes/bin");
	    	if (dir.exists() == false) {
	    		if (!dir.mkdir()) {
	    			Hermes.this.popMsg("Couldn't create bin-directory!");
	    		}
	    	}
	    	dir = new File("/data/data/android.hermes/conf");
	    	if (dir.exists() == false) {
	    		if (!dir.mkdir()) {
	    			Hermes.this.popMsg("Couldn't create conf-directory!");
	    		}
	    	}
	    	dir = new File("/data/data/android.hermes/Sockets");
	    	if (dir.exists() == false) {
	    		if (!dir.mkdir()) {
	    			Hermes.this.popMsg("Couldn't create Sockets-directory!");
	    		}
	    	}
    	}
    	
    }
    /**
     * Copies the essential files to their places, and makes some executable.
     */
    private void moveFiles() {
    	
    	
    	//wpaX.conf
    	this.copyBinary("/data/data/android.hermes/conf/wpa.conf", R.raw.wpa_conf);
    	this.copyBinary("/data/data/android.hermes/conf/tiwlan.ini", R.raw.tiwlan_ini);

    	/*
    	// wifi
    	this.copyBinary("/data/data/android.hermes/bin/wifi", R.raw.wifi);
    	this.copyBinary("/data/data/android.hermes/bin/connect", R.raw.connect);
    	
    	//Change rights to be able to execute the shell scripts
    	runRootCommand("chmod 777 /data/data/android.hermes/bin/wifi");
    	runRootCommand("chmod 777 /data/data/android.hermes/bin/connect");
    	*/
    }
    
    //Creates a file from a resource, "copying" it.
    private void copyBinary(String filename, int resource) {
    	File outFile = new File(filename);
    	InputStream is = this.getResources().openRawResource(resource);
    	byte buf[]=new byte[1024];
        int len;
        try {
        	OutputStream out = new FileOutputStream(outFile);
        	while((len = is.read(buf))>0) {
				out.write(buf,0,len);
			}
        	out.close();
        	is.close();
		} catch (IOException e) {
			Hermes.this.popMsg("Couldn't install file - "+filename+"!");
		}
    }


	
	public void announcePresence() {
		try {
			byte[] buf = new byte[1];
			buf[0] = (byte) 10101010;				
					
			InetAddress group = InetAddress.getByName("192.168.42.1");
			DatagramPacket packet = new DatagramPacket(buf, buf.length, group, 7500);
			DatagramSocket sockan = new DatagramSocket();
			sockan.send(packet);
			
			
		} catch (Exception e) {}
	}
    
    public void quickRegistering() {
    	IntentFilter filter;
    	PingReceiver receiver;
    	filter = new IntentFilter(ListenForFriends.NEW_FRIEND_FOUND);
    	receiver = new PingReceiver();
    	
    	registerReceiver(receiver, filter);
    }
    
    class PingReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context c, Intent i) {
		    Bundle b = i.getExtras();
		    otherIP = (InetAddress) b.get("ip");
		    popMsg(i.getAction());
		    popMsg(otherIP.toString());
		}
    	
    }
}
class ListenForFriends extends Service {
	
	public static final String NEW_FRIEND_FOUND = "Found a new friend to talk to! Yay!";
	
	
	
	Thread t = new Thread(new Runnable() {
		public void run() {
			InetAddress incoming;
			ArrayList<InetAddress> friends = new ArrayList<InetAddress>(3);
			
			while(true) {
				try {
					//Contents of the packet we send doesn't matter at this point
					byte[] buf = new byte[1];
					buf[0] = (byte) 10101010;				
					DatagramPacket packet = new DatagramPacket(buf, buf.length);
					
					//Register as a member of the group
					InetAddress group = InetAddress.getByName("192.168.42.1");
					MulticastSocket ms = new MulticastSocket(7500);
					ms.joinGroup(group);
					
					//wait for an incoming message and extract the senders IP-address
					ms.receive(packet);
					incoming = packet.getAddress();
					
					//if we dont "know" this ip yet...
					if(!friends.contains(incoming)) {
						
						//...add it to our list of friends!
						friends.add(incoming);
						
						//Acknowledge sender by replying
						packet = new DatagramPacket(buf, buf.length, incoming, 7500);
						ms.send(packet);
						
						//Pass the friends IP-address on to the main thread
						informMain(incoming);
					}
					else {
						//This ip has already pinged us recently,
						//so we do nothing. Should probably implement some
						//form of decay...
					}
					
					
				} catch (Exception e) {
					
				}
			}
		}
	});
	
	public void informMain(InetAddress ip) {
		//Create an intent to send and put the IP-address in it
		Intent intent = new Intent(NEW_FRIEND_FOUND);
		intent.putExtra("ip", ip);
		
		//send the intent
		sendBroadcast(intent);    		
	}
	
	@Override
	public void onStart(Intent i, int startID) {
		t.start();
		super.onStart(i, startID);
	}
	
	@Override
	public void onCreate() {
		//t.start();	
		super.onCreate();
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
}

